#include "common/common.h"


namespace iecas_ns
{
    shared_ptr<CCommon> CCommon::sm_intancePtr = nullptr;

    CCommon::CCommon()
    {
        m_data_dq.clear();
        m_dev_fd_stat.clear();
    }

	shared_ptr<CCommon> CCommon::getInstance()
	{
		if(sm_intancePtr == nullptr)
		{
			sm_intancePtr = shared_ptr<CCommon>(new CCommon());
		}
		return sm_intancePtr;
	}

    void CCommon::addDataBack(Value data)
    {
        lock_guard<mutex> lockG(CCommon::m_dataLock);

        m_data_dq.push_back(data);
        // cout << "DATA add dev: " << data[SRC_DEV].asString() << " data: " << data[SRC_DATA].asString() << endl;
        // PLOGD << "DATA add dev: " << data[SRC_DEV].asString() << " data: " << data[SRC_DATA].asString() << endl;
        // cout << "DATA add back" << endl;
        // PLOGD << "DATA add back";
    }

    bool CCommon::getDataFront(Value &data)
    {
        lock_guard<mutex> lockG(CCommon::m_dataLock);

        if(!m_data_dq.empty())
        {
            data = m_data_dq.front();
            // cout << "DATA get dev: " << data[SRC_DEV].asString() << " data: " << data[SRC_DATA].asString() << endl;
            // PLOGD << "DATA get dev: " << data[SRC_DEV].asString() << " data: " << data[SRC_DATA].asString() << endl;
            // cout << "DATA get front" << endl;
            // PLOGD << "DATA get front";
            return true;
        }
        else
        {
            return false;
        }
    }

    void CCommon::delDataFront(void)
    {
        lock_guard<mutex> lockG(CCommon::m_dataLock);

        if(!m_data_dq.empty())
        {
            m_data_dq.pop_front();
            // cout << "DATA del front" << endl;
            // PLOGD << "DATA del front";
        }
    }

    void CCommon::addDev(string dev)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        Value tmp;
        tmp.clear();

        tmp[SRC_FD] = 0;
        tmp[DEV_STAT] = true;
        m_dev_fd_stat[dev] = tmp;
    }

    void CCommon::addDev(string dev, int fd)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        Value tmp;
        tmp.clear();

        tmp[SRC_FD] = fd;
        tmp[DEV_STAT] = true;
        m_dev_fd_stat[dev] = tmp;
    }
    
    bool CCommon::getDevFdStat(string dev, int &fd)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        fd = -1;

        auto tmp = m_dev_fd_stat.find(dev);
        if(tmp != m_dev_fd_stat.end())
        {
            if(tmp->second[DEV_STAT].asBool())
            {
                fd = tmp->second[SRC_FD].asInt();
                return true;
            }
        }

        cout << "get device " << dev << " fd failed or dev disable" << endl;
        PLOGD << "get device " << dev << " fd failed or dev disable";
        return false;
    }

    bool CCommon::getDevStat(string dev)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        auto tmp = m_dev_fd_stat.find(dev);
        if(tmp != m_dev_fd_stat.end())
        {
            return tmp->second[DEV_STAT].asBool();
        }

        cout << "get device " << dev << "not found" << endl;
        PLOGD << "get device " << dev << "not found";
        return false;
    }

    void CCommon::setDevStat(string dev, bool stat)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        auto tmp = m_dev_fd_stat.find(dev);
        if(tmp != m_dev_fd_stat.end())
        {
            tmp->second[DEV_STAT] = stat;
        }
    }

    void CCommon::getDevJson(Value &dev)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        auto map_it = m_dev_fd_stat.cbegin();

        while(map_it != m_dev_fd_stat.cend()) 
        {
            Value tmp;
            tmp = map_it->second;
            tmp[SRC_DEV] = map_it->first;
            dev.append(tmp);
            ++map_it;
        }
    }

    void CCommon::delDev(string dev)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        m_dev_fd_stat.erase(dev);
    }

    void CCommon::getIpNotSocket(vector<string> &dev)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        int fd = -1;
        auto map_it = m_dev_fd_stat.cbegin();

        while(map_it != m_dev_fd_stat.cend())
        {
            if(map_it->first.substr(0, 10) == "192.168.42")
            {
                fd = map_it->second[SRC_FD].asInt();
                if(fd == 0)
                {
                    dev.push_back(map_it->first);
                }
            }
            ++map_it;
        }
    }

    bool CCommon::isIpSocket(string dev)
    {
        lock_guard<mutex> lockG(CCommon::m_dev_fd_stat_Lock);

        int fd = -1;
        auto tmp = m_dev_fd_stat.find(dev);
        if(tmp != m_dev_fd_stat.end())
        {
            fd = tmp->second[SRC_FD].asInt();
            if(fd > 0)
            {
                return true;
            }
        }

        return false;
    }

    void CCommon::addIpName(string ip, string name)
    {
        lock_guard<mutex> lockG(CCommon::m_ip_name_lock);

        m_ip_name[ip] = name;
    }

    void CCommon::delIpName(void)
    {
        lock_guard<mutex> lockG(CCommon::m_ip_name_lock);

        m_ip_name.clear();
    }

    void CCommon::getIpNameJson(Value &dev)
    {
        lock_guard<mutex> lockG(CCommon::m_ip_name_lock);

        auto map_it = m_ip_name.cbegin();

        while(map_it != m_ip_name.cend()) 
        {
            Value tmp;
            tmp[map_it->first] = map_it->second;
            dev.append(tmp);
            ++map_it;
        }
    }
    
    int64_t CCommon::getMsTimeStamp(void)
    {
        chrono::time_point<chrono::system_clock, chrono::milliseconds> tp = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());

        auto tmp = chrono::duration_cast<chrono::milliseconds>(tp.time_since_epoch());

        return tmp.count();
    }
}